import { adminGate, counetOrderYK, counetPositionYK, countHPositionSY, countKeYongMondy, getZhiMaPositionParams, getZmKeys, jingDuSum, keyInfo, newGate, simplifyPosition } from './../../util/index';
import { InjectRepository } from '@nestjs/typeorm';
import { DeleteResult, Repository, UpdateResult } from 'typeorm';
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { User } from './entities/user.entity';
import { formatSuccess, formatError, formatPage, gateRestClient, getTimestamp, jingDuNum, formatTime } from '../../util';
import * as md5 from 'md5';
import { ZhimaService } from '../zhima/zhima.service';
import { PositionsService } from '../positions/positions.service';
import { OrderService } from './../order/order.service';
const dayjs = require('dayjs');

@Injectable()
export class UserService {
  constructor(
    @InjectRepository(User)
    private readonly userRepository: Repository<User>,
    private zhimaService: ZhimaService,
    private positionsService: PositionsService,
    private orderService: OrderService,
  ) {}

  // 新增
  async create(createUserDto: CreateUserDto) {
    if (createUserDto?.id) {
      // 修改
      return this.edit(createUserDto);
    }
    const userinfo = await this.findOne(createUserDto.name);
    if (userinfo) return formatError({ msg: '用户名已存在' });
    createUserDto.password = md5(createUserDto.password);
    const data = await this.userRepository.save(createUserDto);
    return formatSuccess('新增成功');
  }

  // 修改
  async edit(updateUserDto: UpdateUserDto) {
    const data = await this.userRepository.update({ id: updateUserDto.id }, updateUserDto);
    if (data.affected > 0) {
      return formatSuccess('成功');
    } else {
      return formatError({ msg: '失败' });
    }
  }

  // 修改密码
  async eidtPasswrod(updateUserDto: UpdateUserDto) {
    const data = await this.userRepository.update({ id: updateUserDto.id }, { password: md5(updateUserDto.password) });
    if (data.affected > 0) {
      return formatSuccess('成功');
    } else {
      return formatError({ msg: '失败' });
    }
  }

  async findAll(params) {
    const pageNum = params.pageNum || 1;
    const pageSize = params.pageSize || 100;
    // 查询条件
    const where: any = {};
    if (params?.level) where.level = params?.level;
    if (params?.is_active) where.is_active = params?.is_active;
    // 获取总条数
    const total = await this.userRepository.count({ where });
    // 查第几页的数据
    let list = [];
    if (total > 0) {
      list = await this.userRepository.find({
        skip: (pageNum - 1) * pageSize,
        take: pageSize,
        where,
        order: { create_time: 'DESC' },
      });
      // 2.加入芝麻数据
      for (let i = 0; i < list.length; i++) {
        const item = list[i];
        let zhima = null;
        if (item?.zhiMaId !== '-') zhima = await this.zhimaService.findOneById(Number(+item?.zhiMaId));
        list[i].zhima = zhima;
      }
    }
    return formatPage({ pageNum, pageSize, total, list });
  }

  // 通过用户名查找用户信息
  async findOne(username: string) {
    const data = await this.userRepository.findOneBy({ name: username });
    return data;
  }

  // 用户详情
  async detail(params: any) {
    const res: any = await this.findOneById(+params?.id);
    // 获取芝麻账号信息
    const zhima = await this.zhimaService.findOneById(Number(+res?.zhiMaId));
    if (res) {
      return formatSuccess({
        ...res,
        zhima: zhima || {},
      });
    } else {
      return formatError({ msg: '用户不存在' });
    }
  }

  // 通过id查找
  async findOneById(id: number) {
    const data = await this.userRepository.findOneBy({ id });
    return data;
  }

  async remove(id: number) {
    const data = await this.userRepository.delete({ id });
    if (data.affected > 0) {
      return formatSuccess('成功');
    } else {
      return formatError({ msg: '失败' });
    }
  }

  // 合约账户信息
  async futuresAccount() {
    const res: any = await gateRestClient.getFuturesAccount({ settle: 'usdt' });
    return formatSuccess(res);
  }

  // 统一账户信息
  async unifiedAccount() {
    const res: any = await gateRestClient.getUnifiedAccountInfo();
    return formatSuccess(res);
  }

  // 资金流水
  async fundFlow(val, isAdmin = false) {
    const params = {
      ...val,
      settle: 'usdt',
      limit: 1000,
      offset: 0,
    };
    // const res: any = await gateRestClient.getFuturesAccountBook(params);
    let res: any;
    if (!isAdmin) {
      res = await gateRestClient.getFuturesAccountBook(params);
    } else {
      // 1. 查用户的芝麻key，目前只查单用户
      const keys = await getZmKeys(params?.userIds, this);
      if (!keys || keys.length === 0) return formatSuccess([]);
      res = await adminGate(keys[0]).getFuturesAccountBook(params);
    }
    return formatSuccess(res);
  }

  // 芝麻总盈亏
  /*
    获取芝麻账净资产, 用户总资产
    用户总资产 = 芝麻 + 总充值
    每次都全量计算
  */
  async ziChan(params) {
    // 1. 获取用户信息
    const userId = params.id;
    const user: any = (await this.detail({ id: userId }))?.data;
    // const from = user?.ziChanTime !== '0' ? user?.ziChanTime : user?.create_time; // old
    const startTime = user?.create_time;
    const endTime = formatTime(new Date());
    const from = getTimestamp(startTime);
    const to = getTimestamp(endTime);
    // 2. 获取芝麻账净资产
    // 2. 获取历史仓位
    const historyParams = { from, to, userIds: [userId] };
    // console.log('芝麻盈亏，historyParams: ', { startTime, endTime, from, to });
    const positionList: any = (await this.positionsService.historyPositions(historyParams))?.data;
    const positionYKList = positionList.map((item) => {
      const { pnl, pnl_pnl, pnl_fee, pnl_fund } = item?.ysxYingKui;
      return { pnl, pnl_pnl, pnl_fee, pnl_fund };
    });
    const positionYKArr = positionYKList.map(({ pnl, pnl_pnl, pnl_fee, pnl_fund }) => [pnl_pnl, pnl_fee, pnl_fund]);
    const positionSum = countHPositionSY(positionList); // 历史仓位总盈亏
    const lastZiChan = Number(user?.ziChan) || 0;
    const ziChan = positionSum; // 芝麻净资产
    const allMoney = jingDuSum([user?.balance, ziChan]); // 用户总资产
    // 3.更新用户资产、时间
    const ziChanTime = to + '';
    const editParams: any = { id: params.id, ziChan, ziChanTime, allMoney };
    await this.edit(editParams);
    return formatSuccess({
      key: params?.keyInfo?.key,
      chongZhiYuE: user?.balance,
      positionParams: { from, to },
      positionList,
      positionYKList,
      positionYKArr,
      positionSum,
      ziChan,
      allMoney,
      ziChanTongJi: { ziChanTime, lastZiChan, positionSum },
    });
  }

  // 获取可用资产 params: {id}
  async keYongMoney({ id, isNew = false }) {
    // 1. 获取资产
    let ziChanRes: any;
    if (!isNew) {
      ziChanRes = (await this.ziChan({ id }))?.data;
    } else {
      ziChanRes = (await this.zhiMaYingKui({ id }))?.data;
    }
    // console.log('获取可用资产-新：ziChanRes: ', ziChanRes);
    const { allMoney } = ziChanRes;
    // 2. 获取当前仓位
    const positions = (await this.positionsService.positions({ holding: true, userIds: [id] }))?.data;
    const positionsList = simplifyPosition(positions);
    const positionsArr = positions.map(({ baoZhengJin, realised_pnl, pnl_pnl, pnl_fee, pnl_fund }) => [baoZhengJin, realised_pnl, pnl_pnl, pnl_fee, pnl_fund]);
    // 3. 获取当前委托
    const orders = (await this.orderService.orderList({ status: 'open', userIds: [id] }))?.data;
    // 4. 计算可用资产
    const tongJiRes = countKeYongMondy({
      allMoney,
      positions,
      orders,
    });
    return formatSuccess({
      positions,
      positionsList,
      positionsArr,
      orders,
      ziChanRes,
      keYongMoney: tongJiRes?.keYong,
      tongJiRes,
    });
  }

  // 重置用户资产和资产时间
  async resetZiChan() {
    const list: any = (await this.findAll({}))?.data?.list;
    if (list.length === 0) return formatSuccess('成功，无人');
    for (const item of list) {
      const params = {
        id: item.id,
        ziChan: '0',
        ziChanTime: '0',
        allMoney: '0',
      };
      // api
      await this.edit(params);
    }
    return formatSuccess(`成功，处理${list.length}个`);
  }

  // 重置用户资产和资产时间-lisi
  async resetTSYHZiChan() {
    const list: any = (await this.findAll({}))?.data?.list;
    if (list.length === 0) return formatSuccess('成功，无人');
    for (const item of list) {
      if (item.id === 5) {
        const params = {
          id: item.id,
          ziChan: '0',
          ziChanTime: '0',
          allMoney: '0',
        };
        // api
        await this.edit(params);
      }
    }
    return formatSuccess(`成功`);
  }

  // 后台资金流水
  async htfundFlow(params) {
    return await this.fundFlow(params, true);
  }

  // 芝麻盈亏-新
  // 黑洞用户表盈亏+芝麻历史盈亏(同步时间到当前)
  async zhiMaYingKui({ id }) {
    // 1.用户详情
    const user: any = (await this.detail({ id }))?.data;
    const { yingKui: yingKuiLast, create_time } = user;
    // console.log('芝麻盈亏,user,yingKuiLast: ', user, yingKuiLast);
    const timeInfo = getZhiMaPositionParams(user);
    // console.log('芝麻盈亏,timeInfo: ', timeInfo);
    const zhimaPositions = (await this.positionsService.historyPositions(timeInfo))?.data;
    const yingKuiCurrent = countHPositionSY(zhimaPositions); // 历史仓位盈亏
    const yingKui = jingDuSum([yingKuiLast, yingKuiCurrent]);
    const allMoney = jingDuSum([user?.balance, yingKui]); // 用户总资产
    return formatSuccess({
      chongZhiYuE: user?.balance,
      yingKuiLast,
      zhimaPositions,
      yingKuiCurrent,
      yingKui,
      allMoney,
    });
  }

  // 批量修改同步时间
  async editTongbuTime() {
    const list = (await this.findAll({}))?.data?.list.filter((item) => item?.tongBuTime !== '0');
    const arr = list.map((item) => {
      const params = {
        id: item.id,
        // tongBuTime: item?.tongBuTime + ' 24:00:00',
        tongBuTime: item?.tongBuTime.split(' ')[0],
      };
      return this.edit(params);
    });
    const res: any = await Promise.allSettled(arr);
    return formatSuccess('成功');
  }
}
